<template>
    <div>

        <div style="margin-top:20px" ref="refView3d">
        </div>

        <div class="row gap5 item-center" style="margin-top:10px">
            <n-button @click="begin">初始化</n-button>
            <n-switch size="large" v-model="target.bAutoReadDMP" style="width:110px" @on-change="continuousReadChanged">
                <template #checked>
                        连续
                </template>
                <template #unchecked>
                    连续
                </template>
            </n-switch>
        </div>
        
        <div class="row gap10" style="margin-top:10px">
            <div v-show="dataFormat=='quaternion'">X:{{target? target.x.toFixed(3): 0}}°</div>
            <div v-show="dataFormat=='quaternion'">Y:{{target? target.y.toFixed(3): 0}}°</div>
            <div v-show="dataFormat=='quaternion'">Z:{{target? target.z.toFixed(3): 0}}°</div>
            <div v-show="dataFormat=='quaternion'">W:{{target? target.w.toFixed(3): 0}}°</div>

            <div v-show="dataFormat=='euler'">俯仰:{{target? target.pitch.toFixed(2): 0}}°</div>
            <div v-show="dataFormat=='euler'">滚动:{{target? target.roll.toFixed(2): 0}}°</div>
            <div v-show="dataFormat=='euler'">偏航:{{target? target.yaw.toFixed(2): 0}}°</div>
        </div>
        
        <div class="row gap5 item-center" style="margin-top:10px">
            <n-select v-model:value="dataFormat" :options="dataFormatOptions" />
            <n-button @click="read">读取</n-button>
        </div>

    </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, Ref, watch } from 'vue'
import { AppModel } from '../../../../model/AppModel';
import { BePoser } from '../../../../model/parts/BePoser';


const RAD2DGR = 360 / (2 * Math.PI)
const DGR2RAD = (2 * Math.PI) / 360


const props = defineProps<{
    model: AppModel ,
    target: BePoser ,
}>()

const dataFormatOptions = [
    {label: '欧拉角', value: 'euler'} ,
    {label: '四元数', value: 'quaternion'} ,
]
const dataFormat: Ref<"quaternion"|"euler"> = ref("euler")
const refView3d = ref(null) as unknown as Ref<HTMLElement>

let $View3DOuter: any
let part3d: any
let tmp3d: any
let scene: any
let camera: any

onMounted (()=>{
    $View3DOuter = $(refView3d.value)
    
    create3DView()
})

function create3DView() {

    let viewWidth = 280
    let viewHeight = 280

    // THREE.Object3D.DefaultUp.set(0, 0, 1);
    scene = new THREE.Scene()
    camera = new THREE.PerspectiveCamera( 45, viewWidth/viewHeight, 0.1, 2000 )
    camera.position.set(0, 20, -50)
    // camera.lookAt(0, 0, 0)

    let renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setClearColor('rgb(170,170,170)',1.0)
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( viewWidth, viewHeight );

    let controls = new THREE.OrbitControls( camera );
    controls.target.set( 0, -0.2, -0.2 );
    controls.update();

    // let axesHelper = new THREE.AxesHelper( 50 )
    // axesHelper.position.set(0, -2.3, 0)
    // scene.add(axesHelper)

    $View3DOuter.append( renderer.domElement )

    tmp3d = new THREE.Object3D() 
    part3d = new THREE.Object3D() 
    scene.add(part3d)
    
    let loader = new THREE.GLTFLoader();
    loader.load( 'models/part/beposer.gltf', (gltf:any) => {
        console.log(gltf)
        if(!gltf.scene || !gltf.scene.children || !gltf.scene.children.length) {
            console.error("empty gltf")
            return
        }
        let part = gltf.scene.children[0]
        part.rotation.set(0,-Math.PI/4,Math.PI)         // 芯片在pcb上反贴，并且45°斜放
        part3d.add(part)
        part.scale.set(1000,1000,1000) // 单位 m -> mm
        
        // let partAxesHelper = new THREE.AxesHelper( 15 )
        // part.add(partAxesHelper)

        let matStud = new THREE.MeshLambertMaterial({color: 0x14a01})
        let matPCB = new THREE.MeshLambertMaterial({color: 0x0e5c01})
        let matPogopin = new THREE.MeshPhysicalMaterial({
            color:0xbfad6f,
            // 材质像金属的程度. 非金属材料，如木材或石材，使用0.0，金属使用1.0，中间没有（通常）.
            // 默认 0.5. 0.0到1.0之间的值可用于生锈的金属外观
            metalness: 1.0,
            // 材料的粗糙程度. 0.0表示平滑的镜面反射，1.0表示完全漫反射. 默认 0.5
            roughness: 0.6,
            // 反射程度, 从 0.0 到1.0.默认0.5.
            // 这模拟了非金属材料的反射率。 当metalness为1.0时无效
            // reflectivity: 0.5,
        })

        for(let obj of part.children) {
            if(obj.name.substr(0,4)=='stud') {
                setFaceMat(obj, matStud)
            }
            else if(obj.name.substr(0,7)=='pogopin') {
                setFaceMat(obj, matPogopin)
            }
            else if(obj.name.substr(0,4)=='pcb') {
                setFaceMat(obj, matPCB)
            }
        }
    } )

    var gridHelper = new THREE.GridHelper( 1000, 30, 0x444444, 0x888888 )
    gridHelper.position.y = -2.4
    scene.add( gridHelper )
    
    createLight("l1", [100,50,100])
    createLight("l2", [-100,50,100])
    createLight("l3", [100,50,-100])
    createLight("l4", [-100,50,-100])

    
    let hl = new THREE.HemisphereLight( 0x443333, 0x111122 )
    ;(window as any).hl = hl
    scene.add( hl )
    // let hlhelper = new THREE.HemisphereLightHelper( hl, 5 );
    // scene.add( hlhelper )
    // this.addShadowedLight( 100, 100, 100, 0xffffff, 1.35 )
    // this.addShadowedLight( 50, -100, 100, 0xffaa00, 1 )


    const animate = () => {
        requestAnimationFrame( animate );
        renderer.render( scene, camera );
    };
    animate();

    ;(window as any).view3d = {
        camera: camera ,
        part: part3d ,
        scene: scene ,
        grid: gridHelper ,
    }
    
}
function createLight(name:string, pos: number[]) {
    var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 )
    directionalLight.position.set(...pos)
    directionalLight.name = name

    // var axesHelper = new THREE.DirectionalLightHelper( directionalLight, 5 )
    // scene.add(axesHelper)

    scene.add( directionalLight )
    window[name] = directionalLight
}
// addShadowedLight( x, y, z, color, intensity ) {

//     const directionalLight = new THREE.DirectionalLight( color, intensity );
//     directionalLight.position.set( x, y, z );
//     scene.add( directionalLight );

//     directionalLight.castShadow = true;

//     const d = 1;
//     directionalLight.shadow.camera.left = - d;
//     directionalLight.shadow.camera.right = d;
//     directionalLight.shadow.camera.top = d;
//     directionalLight.shadow.camera.bottom = - d;

//     directionalLight.shadow.camera.near = 1;
//     directionalLight.shadow.camera.far = 4;

//     directionalLight.shadow.bias = - 0.002;

// }

function setFaceMat(obj:any, mat: any) {
    for(let face of obj.children) {
        face.material = mat
    }
}

async function begin() {
    props.target.remoteBegin()
}

async function read() {
    await props.target.readRemote()
}

function continuousReadChanged(isOn:boolean) {
    if(!props.target)
        return
    if(isOn) {
        props.target.startReadDMP()
    }
    else {
        props.target.stopReadDMP()
    }
}

function onTargetChanged() {
    if(part3d) {
        // part3d.rotation.set(
        //     props.target.pitch*DGR2RAD,
        //     props.target.roll*DGR2RAD,
        //     props.target.yaw*DGR2RAD,
        // )
        // 四元数转欧拉角
        tmp3d.quaternion.set( props.target.x, props.target.y, props.target.z, props.target.w )
        // 交换 xyz 轴（模型z轴向上，three.js y轴向上）
        part3d.rotation.set( -tmp3d.rotation.y, tmp3d.rotation.x, tmp3d.rotation.z )

        props.target.pitch = part3d.rotation.x * RAD2DGR
        props.target.yaw = part3d.rotation.y * RAD2DGR
        props.target.roll = part3d.rotation.z * RAD2DGR
    }

}
watch(()=>props.target.dataUpdateTime, onTargetChanged)
    
    
</script>